/*
* |NGPKG|HEADER|FILE DATA|FILE LIST|
* NGPKG: fixed 32 char.
* HEADER: |fb|fc|db|
*   fb: file begin pos, fixed 8 char(int64)
*   fc: file count, fixed 8 char(int64)
*   db: data begin pos, fixed 8 char(int64)
* FILE DATA: not fixed
* FILE LIST: not fixed, at last.
*   |GROUP|GROUP|GROUP|
*     GROUP: |fb|fs|fns|fn|
*       fb: file data pos. fixed 8 char(int64)
*       fs: file data size. fixed 8 char(int64)
*       fns: file name size. fixed 8 char(int64)
*       fn: file name, 'a.txt\0'
*
* /----------------------------------------------------------------------------------\
* |NGPKG|        HEADER           | FILE DATA | FILE LIST                            |
  |----------------------------------------------------------------------------------|
* |     |                         |           |                                      |
* |NGPKG|filePos|fileCount|dataPos| fileData  |filePos|fileSize|fileNameSize|fileName|
* |     |                         |           |            fileCount                 |
* \----------------------------------------------------------------------------------/
*/
#include "package.h"

#include <zlib.h>

namespace ng {

Package::Package(bool readFromDisk) : readFromDisk_(readFromDisk) {}
Package::~Package() { unloadAll(); }
bool Package::load(const nt::String &pkg) {
  if (pkg.isEmpty()) return false;
  auto item = getItem(pkg);
  if (item) return false;
  PackageItem pi;
  pi.name = pkg;
  if (!readFromDisk_) {
    if (!loadItem(pi))
      return false;
  }
  pkgs_.pushBack(nt::move(pi));
  return true;
}
void Package::unload(const nt::String &pkg) {
  if (pkg.isEmpty()) return;
  for (auto it = pkgs_.begin(); it != pkgs_.end(); ++it) {
    if ((*it).name == pkg) {
      unloadItem(*it);
      pkgs_.erase(it);
      break;
    }
  }
}
void Package::unloadAll() {
  for (auto it = pkgs_.begin(); it != pkgs_.end(); ++it) {
    unloadItem(*it);
  }
  pkgs_.clear();
}
const Package::PackageItem* Package::getItem(const nt::String &pkg) const {
  if (pkg.isEmpty()) return nullptr;
  for (auto it = pkgs_.begin(); it != pkgs_.end(); ++it) {
    if ((*it).name == pkg)
      return &(*it);
  }
  return nullptr;
}
nt::UniquePtr<Package::PackageData> Package::getData(const PackageItem *item, const nt::String &file) const {
  if (!item || file.isEmpty()) return nt::UniquePtr<Package::PackageData>(0);
  const PackageFile *pf = nullptr;
  for (auto it = item->files_.begin(); it != item->files_.end(); ++it) {
    if ((*it).name == file)
      pf = &(*it);
  }
  if (!pf) return nt::UniquePtr<Package::PackageData>(0);

  if (!readFromDisk_)
    return getFileData(pf);
  return getFileData(item->name + "/" + file);
}
nt::UniquePtr<Package::PackageData> Package::getData(const nt::String &pkg, const nt::String &file) const {
  auto pi = getItem(pkg);
  return getData(pi, file);
}
nt::UniquePtr<Package::PackageData> Package::getData(const nt::String &file) const {
  if (file.isEmpty()) return nt::UniquePtr<Package::PackageData>(0);
  for (auto &pi : pkgs_) {
    auto pd = getData(&pi, file);
    if (pd) return pd;
  }
  return nt::UniquePtr<Package::PackageData>(0);
}


bool Package::loadItem(PackageItem &pi) {
  return false;
}
void Package::unloadItem(PackageItem &pi) {
}
nt::UniquePtr<Package::PackageData> Package::getFileData(const PackageFile *pf) const {
  return nt::UniquePtr<Package::PackageData>(0);
}
nt::UniquePtr<Package::PackageData> Package::getFileData(const nt::String &file) const {
  return nt::UniquePtr<Package::PackageData>(0);
}

} // end namespace ng